﻿using System.Collections.Generic;
using System.Drawing;
using System.Linq;
using RoMBot.Database;

namespace RoMBot.Classes
{
    public static class Store
    {
        static Store()
        {
            Items = new List<StoreItem>();
        }

        private static Player Player
        {
            get { return Bot.Player; }
        }

        public static void Update()
        {
            var target = Player.Target;
            if ( target == null || target.Type != ObjectType.NpcOrNode || !( bool ) Helpers.RoMScript( "StoreFrame:IsVisible()" ) )
            {
                Id = 0;
                Name = GameObject.UnknowName;
                CanRepair = false;
                Items.Clear();
                return;
            }
            if ( target.Id == Id )
            {
                return;
            }
            Id = target.Id;
            Name = target.Name;

            // number of items in store
            var sellItems = Helpers.RoMScript<int>( "GetStoreSellItems()" );
            Items.Clear();
            for ( var i = 1; i <= sellItems; i++ )
            {
                //local __, name, price, __, __, __, maxheap = RoMScript("GetStoreSellItemInfo("+ i +")")
                var itemInfo = Helpers.RoMScript<List<object>>( "GetStoreSellItemInfo(" + i + ")" );
                if ( itemInfo == null )
                {
                    continue;
                }
                var itemLink = Helpers.ParseItemLink( Helpers.RoMScript<string>( "GetStoreSellItemLink(" + i + ")" ) );
                if ( itemLink == null )
                {
                    continue;
                }
                var item = new StoreItem
                           {
                               Id = itemLink.Id,
                               Name = ( string ) itemInfo[ 1 ],
                               Price = ( int ) itemInfo[ 2 ],
                               MaxHeap = ( int ) itemInfo[ 6 ],
                               Type = Database.Database.Consumables.ContainsKey( itemLink.Id ) ? Database.Database.Consumables[ itemLink.Id ].Type : 0,
                               Level = Database.Database.Consumables.ContainsKey( itemLink.Id ) ? Database.Database.Consumables[ itemLink.Id ].Level : 0
                           };
                Items.Add( item );
            }

            // Is there a repair button.
            CanRepair = Helpers.RoMScript<bool>( "IsStoreCanFix()" );
        }

        public static bool BuyConsumable( ConsumableType consumable, int count = 0 )
        {
            if ( consumable == ConsumableType.None || count == 0 )
            {
                return false;
            }

            var availableItem = Items.FirstOrDefault( i => i.Type == consumable && i.Level == Items.Where( itms => itms.Level <= Player.Level ).Max( itm => itm.Level ) );
            if ( availableItem == null )
            {
                return false;
            }
            Player.Inventory.Update();
            var consumablesInInv = Player.Inventory.Items.Where( i => Database.Database.Consumables.ContainsKey( i.Id ) && Database.Database.Consumables[ i.Id ].Type == consumable && Database.Database.Consumables[ i.Id ].Level <= Player.Level ).ToList().Sum( c => c.ItemCount );
            if ( consumablesInInv >= count )
            {
                return false;
            }
            return BuyItem( availableItem.Id, count - consumablesInInv );
        }

        public static bool BuyItem( object nameIdOrIndex, int quantity = 1 )
        {
            if ( quantity <= 0 )
            {
                Bot.Printf( Color.Yellow, "Bad argument for quantity in 'Store.BuyItem': {0}", quantity );
                return false;
            }
            var index = -1;
            if ( nameIdOrIndex is int && ( int ) nameIdOrIndex < Items.Count )
            {
                index = ( int ) nameIdOrIndex;
            }
            else if ( nameIdOrIndex is int || nameIdOrIndex is string )
            {
                index = Items.FindIndex( i => nameIdOrIndex is int ? ( int ) nameIdOrIndex == i.Id : ( string ) nameIdOrIndex == i.Name );
            }
            if ( index < 0 )
            {
                Bot.Error( "Bad argument passed to Store.BuyItem: " + nameIdOrIndex );
                return false;
            }
            var buyMaxHeap = Items[ index ].MaxHeap;
            do
            {
                // index + 1 because its lua's table (base 1)
                Bot.Printf( Color.Orange, "Shopping for: {0} {1}", quantity, Items[ index ].Name );
                if ( quantity > buyMaxHeap )
                {
                    Helpers.RoMScript( "StoreBuyItem(" + ( index + 1 ) + "," + buyMaxHeap + ")" );
                    quantity -= buyMaxHeap;
                }
                else
                {
                    Helpers.RoMScript( "StoreBuyItem(" + ( index + 1 ) + "," + quantity + ")" );
                    quantity = 0;
                }
                Helpers.Yrest( 1000 );
            } while ( quantity > 0 );

            return true;
        }

        public static int Id { get; private set; }
        public static string Name { get; private set; }
        public static bool CanRepair { get; private set; }
        public static List<StoreItem> Items { get; private set; }
    }
}
